package com.dmp.onlinestore.controller;

import com.dmp.onlinestore.system.Settings;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


// Root of hierarchy of classes that handle incoming actions.
public abstract class ActionHandler {
	
	protected static int INTERNAL_ASSERTION = 0;
	protected static int EXTERNAL_ASSERTION = 0;
	
	// The request we are handling and the response we are generating.
	private HttpServletRequest request;
	private HttpServletResponse response;
	private Map parmMap;
	protected int numRequestParms = -1;
	
	public ActionHandler (HttpServletRequest request, HttpServletResponse response) {
		this.request = request;
		this.response = response;
	}
	
	// Asserts number of request parameters.
	protected void assertNumMapEntries(int numEntries, int assertionScope) throws ControllerValidationException {
		Map params = getParmMap();
		if (params.keySet().size() != numEntries) {
			if (assertionScope == INTERNAL_ASSERTION) {
				throw new ControllerInternalValidationException("Incorrect number of parameters");
			}
			else {
				throw new ControllerExternalValidationException("Incorrect number of parameters");
			}
		}
	}

	// Asserts max number of request parameters.
	protected void assertMaxNumMapEntries(int maxEntries, int assertionScope) throws ControllerValidationException {
		Map params = getParmMap();
		if (params.keySet().size() > maxEntries) {
			if (assertionScope == INTERNAL_ASSERTION) {
				throw new ControllerInternalValidationException("Exceeded max number of supported parameters");
			}
			else {
				throw new ControllerExternalValidationException("Exceeded max number of supported parameters");
			}
		}
	}
	
	
	// Asserts that the given parm is present, with the given number of occurrances.
	// Returns the string array for that parm.
	protected String[] assertParmPresent(String parmName, int count, int assertionScope) throws ControllerValidationException {
		Map params = getParmMap();
		boolean isPresent = false;
		int occurrences   = -1;
		if (params.containsKey(parmName)) {
			isPresent = true;
			String[] parmArray = (String[]) params.get(parmName);
			occurrences = parmArray.length;
			if (occurrences == count) {
				return parmArray;
			}
		}
		String errorString = "Parm presence assertion failed (" + isPresent + ", " + occurrences + ")";
		if (assertionScope == INTERNAL_ASSERTION) {
			throw new ControllerInternalValidationException(errorString);
		}
		else {
			throw new ControllerExternalValidationException(errorString);
		}
	}
	
	
	// Template method. Must be overridden.
	//public void handle() throws ServletException, IOException {
	private void parse() throws ControllerValidationException {
		// Parse the incoming parameters, validate them, then process the incoming request.
	    setParmMap(getRequest().getParameterMap());
	    
	    // Return if debugging is not turned on.
	    if (!Settings.CONSOLE_DEBUG_ON) {
	    	return;
	    }
	    // Print debug information.
	    Map params = getParmMap();
	    Iterator i = params.keySet().iterator();
	    boolean parmsPresent = false;
	    System.out.println(Settings.DEBUG_SEPERATOR);
	    System.out.println("com.css.controller.ActionHandler/parse(): Request parameters:");
	    while (i.hasNext()) {
	    	parmsPresent = true;
	    	StringBuffer buf = new StringBuffer("");
	        String key = (String) i.next();
	        //String value = ((String[]) params.get( key ))[ 0 ];
	        String[] valueArray = (String[]) params.get(key);
	        for (int j=0; j < valueArray.length; j++) {
	        	if (buf.length() != 0) {
	        		buf.append(",");
	        	}
	        	buf.append(valueArray[j]);
	        }
	        System.out.println(    "\"" + key + "\" = \"" + buf.toString() + "\"");
	    }
	    if (! parmsPresent) {
	    	System.out.println("    None.");
	    }
	}
	
	protected int getNumRequestParms() {
		return parmMap.size();
	}
	
	// Template method. Must be overridden.
	//public void handle() throws ServletException, IOException {
	public void handle() throws ControllerException {
		// Parse the incoming parameters, validate them, then process the incoming request.
		parse();
		validate();
		process();
	}

	// Template method (must be overridden). Performs any required
	// validation of contents (parameters) of the incoming request.
	//public abstract void validate();
	protected abstract void validate() throws ControllerValidationException;
	
	// Template method (must be overridden). This is the core logic 
	// of the "controller" piece of the MVC pattern. 
	//
	// Prototypical patterns is to determine what piece of business
	// logic to invoke ("model"), invoke it, gather the results and
	// then hand control to the appropriate JSP ("view") to format the 
	// display for the user.
	//public abstract void process() throws ServletException, IOException;
	protected abstract void process() throws ControllerException;
		
	protected HttpServletRequest getRequest() {
		return this.request;
	}
	protected HttpServletResponse getResponse() {
		return this.response;
	}
	protected Map getParmMap() {
		return this.parmMap;
	}
	private void setParmMap(Map m) {
		this.parmMap = m;
	}
}
